package com.duoqin.syncassistant.ui;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.duoqin.common.data.QRCodeResponse;
import com.duoqin.common.ui.AbsActivity;
import com.duoqin.syncassistant.R;
import com.duoqin.syncassistant.Utils;
import com.duoqin.syncassistant.data.BackupFileDownloadResponse;
import com.duoqin.syncassistant.viewmodel.AppViewModel;
import com.duoqin.syncassistant.viewmodel.BaseViewModel;
import com.duoqin.syncassistant.viewmodel.VCardViewModel;
import com.jkb.vcedittext.VerificationCodeEditText;

import java.io.File;
import java.util.List;

public class RemoteAddContactsActivity extends AbsActivity
        implements VerificationCodeEditText.OnVerificationCodeChangedListener {

    private final String PREF_KEY_SHOW_QR_VIEW = "show_qr_view";

    private SharedPreferences mSharedPreferences;

    private TextView mInputCode, mAddContacts;
    private AppViewModel mAppViewModel;
    private VCardViewModel mVCardViewModel;
    private View mQrCodeView, mInputCodeView, mProgressView;
    private ImageView mQrCodeIv;
    private VerificationCodeEditText mCodeInput;
    private String mCode;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_remote_add_contacts);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        setupTitle(getString(R.string.remote_add_contacts));
        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        mAddContacts = findViewById(R.id.duoqin_add_contacts);
        mInputCode = findViewById(R.id.duoqin_input_retrieve_code);
        mQrCodeView = findViewById(R.id.qr_code_view);
        mQrCodeIv = mQrCodeView.findViewById(R.id.qr_code);
        mInputCodeView = findViewById(R.id.input_code_view);
        mProgressView = mInputCodeView.findViewById(R.id.sync_progress);
        mCodeInput = mInputCodeView.findViewById(R.id.code_input);
        mCodeInput.setOnVerificationCodeChangedListener(this);
        mInputCode.setOnClickListener(this);
        mAddContacts.setOnClickListener(this);
        setupModelObserver();
        if (needShowQRView()) {
            showQRView();
        } else {
            showInputCodeView();
        }
    }


    private void showQRView() {
        hideSoftInput();
        mInputCodeView.setVisibility(View.GONE);
        showQRImage(getApplication().getCacheDir() + "/" + AppViewModel.APP_QRCODE_FILE);
        mQrCodeView.setVisibility(View.VISIBLE);
    }

    private void showInputCodeView() {
        showSoftInput();
        if (needShowQRView()) {
            setHideQRView();
        }
        mQrCodeView.setVisibility(View.GONE);
        mInputCodeView.setVisibility(View.VISIBLE);
        mCodeInput.requestFocus();
    }

    private void hideSoftInput() {
        Log.i("hideSoftInput", "mQrCodeView");
        View view = getCurrentFocus();
        if (view != null) {
            InputMethodManager inputMethodManager = (InputMethodManager) view.getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
            Log.i("hideSoftInput", "mQrCodeView2");
        }
    }

    private void showSoftInput() {
        mCodeInput.requestFocus();
        Log.i("hideSoftInput", "mQrCodeView");
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
        inputMethodManager.showSoftInput(mCodeInput, InputMethodManager.SHOW_IMPLICIT);
    }

    private void attempDownloadVCard() {
        if (mCode == null || mCode.length() != 6) return;
        mVCardViewModel.downloadVCard(mCode);
        showProgress(true, false);
    }

    private void setupModelObserver() {
        mAppViewModel = ViewModelProviders.of(this).get(AppViewModel.class);
        final Observer<QRCodeResponse> appQRCodeObserver = new Observer<QRCodeResponse>() {
            @Override
            public void onChanged(@Nullable QRCodeResponse response) {
                Log.i(TAG, "onChanged QRCodeResponse = " + response);
                if (response != null) {
                    Log.d(TAG, "onChanged code = " + response.getCode()
                            + "; msg = " + response.getMsg());
                    if (BaseViewModel.SERVER_RESULT_SUCCESS == response.getCode()) {
                        Log.d(TAG, "onChanged qrCodePath = " + response.getQrCode());
                        showQRImage(response.getQrCode());
                    }
                }
            }
        };
        mAppViewModel.appQRCodeResponse().observe(this, appQRCodeObserver);

        mVCardViewModel = ViewModelProviders.of(this).get(VCardViewModel.class);
        final Observer<BackupFileDownloadResponse> vCardDownloadObserver =
                new Observer<BackupFileDownloadResponse>() {
                    @Override
                    public void onChanged(@Nullable BackupFileDownloadResponse response) {
                        Log.i(TAG, "onChanged BackupFileDownloadResponse = " + response);
                        if (response != null) {
                            Log.i(TAG, "response.getCode() = " + response.getCode());
                            if (BaseViewModel.SERVER_RESULT_SUCCESS == response.getCode()) {
                                String vCardPath = response.getPath();
                                Log.i(TAG, "vCardPath = " + vCardPath);
                                Uri fileUri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() +
                                        ".fileProvider", new File(vCardPath));
                                Intent importIntent = new Intent(Intent.ACTION_VIEW);
                                Log.d("fileUrl", fileUri.toString());
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                    importIntent.setDataAndType(fileUri, "text/x-vcard");
                                    grantUriPermission(getApplicationContext(), fileUri, importIntent);
                                } else {
                                    importIntent.setDataAndType(Uri.fromFile(new File(vCardPath)),
                                            "text/x-vcard");
                                }
                                importIntent.putExtra("account_name",
                                        Utils.LOCAL_CONTACT_ACCOUNT_NAME);
                                importIntent.putExtra("account_type",
                                        Utils.LOCAL_CONTACT_ACCOUNT_TYPE);
                                importIntent.addCategory(Intent.CATEGORY_DEFAULT);
                                startActivity(importIntent);

                                finish();
                                return;
                            } else if (BaseViewModel.SERVER_RESULT_ERROR_INVALID_CODE ==
                                    response.getCode()) {
                                Toast.makeText(getApplicationContext(),
                                        R.string.error_incorrect_code, Toast.LENGTH_SHORT).show();
                                showProgress(false, true);
                                return;
                            }
                        }
                        showProgress(false, false);
                        Toast.makeText(getApplicationContext(), R.string.retrieve_vcard_failed,
                                Toast.LENGTH_SHORT).show();
                    }
                };
        mVCardViewModel.vcardDownLoadResponse().observe(this, vCardDownloadObserver);
    }

    private static void grantUriPermission(Context context, Uri fileUri, Intent intent) {
        List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
    }


    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.duoqin_input_retrieve_code) {
            showInputCodeView();
        } else if (v.getId() == R.id.duoqin_add_contacts) {
            showQRView();
        }
    }

    /**
     * Shows the progress UI and hides the login form.
     */
    private void showProgress(final boolean show, final boolean requestFocus) {
        if (show) {
            mCodeInput.setVisibility(show ? View.GONE : View.VISIBLE);
            mAddContacts.setVisibility(show ? View.GONE : View.VISIBLE);
        }

        int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
        mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
        mProgressView.animate().setDuration(shortAnimTime).alpha(
                show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
                mCodeInput.setVisibility(show ? View.GONE : View.VISIBLE);
                mAddContacts.setVisibility(show ? View.GONE : View.VISIBLE);
                if (requestFocus) {
                    mCodeInput.requestFocus();
                }
            }
        });
    }

    private boolean needShowQRView() {
        return mSharedPreferences.getBoolean(PREF_KEY_SHOW_QR_VIEW, true);
    }

    private void setHideQRView() {
        mSharedPreferences.edit().putBoolean(PREF_KEY_SHOW_QR_VIEW, false).apply();
    }

    private Bitmap getQRImage(String path) {
        Bitmap imageBitmap = null;
        synchronized (AppViewModel.appLockObj) {
            try {
                imageBitmap = BitmapFactory.decodeFile(path);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        Log.d(TAG, "showQRImage path = " + path + "; bitmap = " + imageBitmap);
        return imageBitmap;
    }

    private void showQRImage(String path) {
        Bitmap imageBitmap = getQRImage(path);
        // we tried getting image in MainActivity. If found, show it. Otherwise try getting it again
        if (imageBitmap != null) {
            mQrCodeIv.setImageBitmap(imageBitmap);
        } else {
            if (Utils.isNetWorkAvilable(this)) {
                if (mAppViewModel != null) {
                    mAppViewModel.getAppQRCode();
                }
            } else {
                Toast.makeText(this, R.string.network_not_avaiable, Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public void onVerCodeChanged(CharSequence s, int start, int before, int count) {
        if (s != null && s.length() != 6) {
            // TODO
        }
    }

    @Override
    public void onInputCompleted(CharSequence s) {
        mCode = s.toString();
        attempDownloadVCard();
    }
}
